package com.kgis.map.geometry {
	import com.kgis.map.Map;
	import com.kgis.map.common.enum.AlignmentEnum;
	import com.kgis.map.common.enum.GeoTypeEnum;
	import com.kgis.map.common.util.Evals;
	import com.kgis.map.common.util.GMath;
	import com.kgis.map.common.util.Util;
	import com.kgis.map.constant.LayerIdConstants;
	import com.kgis.map.feature.Feature;
	import com.kgis.map.geometry.AbstractGeometry;
	import com.kgis.map.geometry.IPointGeometry;
	import com.kgis.map.geometry.basetype.Extent;
	import com.kgis.map.geometry.basetype.Location;
	import com.kgis.map.geometry.basetype.Pixel;
	import com.kgis.map.handler.feature.draw.AnchorPoint;
	import com.kgis.map.handler.feature.draw.snap.SnapTypeEnum;
	import com.kgis.map.layer.GraphicLayer;
	import com.kgis.map.style.IStyle;
	import com.kgis.map.style.PointStyle;
	
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.Loader;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.geom.ColorTransform;
	import flash.geom.Matrix;
	import flash.net.URLRequest;
	
	import mx.controls.Alert;
	import mx.states.OverrideBase;
	
	import spark.components.Image;
	
	[Bindable]
	[RemoteClass(alias="com.kgis.map.model.geometry.PointGeometry")]
	/**
	 * 点
	 */
	public class PointGeometry extends AbstractGeometry implements IPointGeometry {
		private var _x:Number;
		
		private var _y:Number;
		
		private var _z:Number;
		
		private var pointstyle:PointStyle=null;
		private var fea:Feature=null;
		private var _map:Map=null;
		private var symbolSprite:Sprite=null;
		private var btm:Bitmap=null;
		
		
		
		public function PointGeometry(x:Number = 0, y:Number = 0, z:Number = 0) {
			super();
			this.x = x;
			this.y = y;
			this.z = z;
		}
		
		/**
		 * 绘制点几何体
		 */
		override public function draw(sprite:Sprite, geoStyle:IStyle, map:Map):void {
			/**feature对象*/
			var myMatrix:ColorTransform = null;
			
			if (!sprite) {
				trace("point sprite为空!");
				return;
			}
			fea = sprite as Feature;
			_map=map;
			
			if (!this.isValid()) {
				trace("点几何体不符合规范,point objectid=" + fea.objectId.toString());
				return;
			}
			if (!map) {
				trace("map为空,point objectid=" + fea.objectId.toString());
				return;
			}
			
			if (!geoStyle) {
				trace("geoStyle为空,point objectid=" + fea.objectId.toString());
				return;
			}
			
			
			pointstyle= geoStyle as PointStyle;
			
			if (!(pointstyle is PointStyle)) {
				trace("点图形数据有误：objectid=" + fea.objectId.toString() + ",layerid=" + fea.layer.id.toString());
				return;
			}
			
			
			
			
			if(pointstyle.displayMode==1)
			{
				
				
				var symbolClass:Class = pointstyle.symbolClass;
				if (symbolClass == null) {
					trace("点符号图标不存在");
					return;
				}
				//var symbolSprite:Sprite=null;
				if (!symbolSprite) {
					symbolSprite = new symbolClass() as Sprite;
					sprite.addChild(symbolSprite);
				}
				
				myMatrix = new ColorTransform(1, 1, 1, 1, Util.rChannel(pointstyle.color), Util.gChannel(pointstyle.color), Util.bChannel(pointstyle.color));
				var nAlpha:int = pointstyle.alpha;
				//myMatrix.color = pointstyle.color;
				symbolSprite.alpha = nAlpha;
				symbolSprite.transform.colorTransform = myMatrix;
				
				setGeometryStyle(symbolSprite,map);
				
				//sprite.addChild(symbolSprite);
				
				//编辑状态显示锚点
				if (fea.editing) {
					drawAnchorPoint(sprite, map);
				}
			}
			else
			{
				
				if(!btm)
				{
					
					var loader:Loader=new Loader();
					loader.load(new URLRequest(pointstyle.symbolName));
					loader.contentLoaderInfo.addEventListener(Event.COMPLETE,onLoadComplete); 
					btm=new Bitmap();
				}
				else
				{
					setGeometryStyle(btm,_map);
				}
			}
			
			
		}
		
		
		private function onLoadComplete(e:Event):void{
			var loader:Loader=e.target.loader as Loader;//转变类型为Loader
			
			//得到加载的BitmapData
			//var bmd:BitmapData = Bitmap(e.currentTarget.content).bitmapData;
			//var myBitmap:BitmapData = new BitmapData(loader.width, loader.height,true,0x00FFFFFF);					

			
			btm=Bitmap(loader.content);
			fea.addChild(btm);
			setGeometryStyle(btm,_map);
			
			
		}
		
		private function setGeometryStyle(symbolSprite:Object,map:Map):void
		{
			
			var nAlignMent:int = pointstyle.alignment;		
			var nRotation:Number = Evals.evalToNumber(fea.fieldsMap, pointstyle.rotation);
	
			var scale:Number = 1.0;
			var tempScale:String;
			if (pointstyle.scale.length > map.zoom) {
				tempScale = pointstyle.scale[map.zoom];
			}
			else {
				tempScale = pointstyle.scale[0];
			}
			scale = Evals.getSizeByLevel(tempScale, map.zoom);
			
			var point:Pixel = map.getLayerPxFromLocation(new Location(this.x, this.y));
			//对齐方式
			if (nAlignMent == AlignmentEnum.LEFTTOP) {
				symbolSprite.y = point.y;
				symbolSprite.x = point.x;
			}
			else if (nAlignMent == AlignmentEnum.MIDETOP) {
				symbolSprite.y = point.y - symbolSprite.width * scale / 2 * Math.cos(90 - nRotation * Math.PI / 180);
				symbolSprite.x = point.x - symbolSprite.width * scale / 2 * Math.sin(90 - nRotation * Math.PI / 180);
			}
			else if (nAlignMent == AlignmentEnum.RIGHTTOP) {
				symbolSprite.y = point.y - symbolSprite.width * scale * Math.cos(Math.PI / 2 - nRotation * Math.PI / 180);
				symbolSprite.x = point.x - symbolSprite.width * scale * Math.sin(Math.PI / 2 - nRotation * Math.PI / 180);
			}
			else if (nAlignMent == AlignmentEnum.LEFTMID) {
				symbolSprite.y = point.y - symbolSprite.height * scale / 2 * Math.cos(0 - nRotation * Math.PI / 180);
				symbolSprite.x = point.x - symbolSprite.height * scale / 2 * Math.sin(0 - nRotation * Math.PI / 180);
			}
			else if (nAlignMent == AlignmentEnum.CENTER) {
				symbolSprite.y = point.y - Math.sqrt(symbolSprite.width * scale * symbolSprite.width * scale + symbolSprite.height * scale * symbolSprite.height * scale) / 2 * Math.cos(Math.atan(symbolSprite.width * scale / (symbolSprite.height * scale)) - nRotation * Math.PI / 180);
				symbolSprite.x = point.x - Math.sqrt(symbolSprite.width * scale * symbolSprite.width * scale + symbolSprite.height * scale * symbolSprite.height * scale) / 2 * Math.sin(Math.atan(symbolSprite.width * scale / (symbolSprite.height * scale)) - nRotation * Math.PI / 180);
			}
			else if (nAlignMent == AlignmentEnum.RIGHTMID) {
				symbolSprite.y = point.y - Math.sqrt(symbolSprite.width * scale * symbolSprite.width * scale + symbolSprite.height * scale * symbolSprite.height * scale / 4) * Math.cos(Math.atan(symbolSprite.width * scale * 2 / (symbolSprite.height * scale)) - nRotation * Math.PI / 180);
				symbolSprite.x = point.x - Math.sqrt(symbolSprite.width * scale * symbolSprite.width * scale + symbolSprite.height * scale * symbolSprite.height * scale / 4) * Math.sin(Math.atan(symbolSprite.width * scale * 2 / (symbolSprite.height * scale)) - nRotation * Math.PI / 180);
			}
			else if (nAlignMent == AlignmentEnum.LEFTBOTTOM) {
				symbolSprite.y = point.y - symbolSprite.height * scale * Math.cos(0 - nRotation * Math.PI / 180);
				symbolSprite.x = point.x - symbolSprite.height * scale * Math.sin(0 - nRotation * Math.PI / 180);
			}
			else if (nAlignMent == AlignmentEnum.MIDBOTTOM) {
				symbolSprite.y = point.y - Math.sqrt(symbolSprite.width * scale * symbolSprite.width * scale / 4 + symbolSprite.height * scale * symbolSprite.height * scale) * Math.cos(Math.atan(symbolSprite.width * scale * 0.5 / (symbolSprite.height * scale)) - nRotation * Math.PI / 180);
				symbolSprite.x = point.x - Math.sqrt(symbolSprite.width * scale * symbolSprite.width * scale / 4 + symbolSprite.height * scale * symbolSprite.height * scale) * Math.sin(Math.atan(symbolSprite.width * scale * 0.5 / (symbolSprite.height * scale)) - nRotation * Math.PI / 180);
			}
			else if (nAlignMent == AlignmentEnum.RIGHTBOTTOM) {
				symbolSprite.y = point.y - Math.sqrt(symbolSprite.width * scale * symbolSprite.width * scale + symbolSprite.height * scale * symbolSprite.height * scale) * Math.cos(Math.atan(symbolSprite.width * scale / (symbolSprite.height * scale)) - nRotation * Math.PI / 180);
				symbolSprite.x = point.x - Math.sqrt(symbolSprite.width * scale * symbolSprite.width * scale + symbolSprite.height * scale * symbolSprite.height * scale) * Math.sin(Math.atan(symbolSprite.width * scale / (symbolSprite.height * scale)) - nRotation * Math.PI / 180);
			}
			
			symbolSprite.rotation = nRotation;
			
			symbolSprite.scaleX = scale;
			symbolSprite.scaleY = scale;
		}
		override public function getExtent():Extent {
			return new Extent(x, y, x, y);
		}
		
		override public function getGeometryType():int {
			return GeoTypeEnum.POINTGEOMETRY;
		}
		
		public function get y():Number {
			return _y;
		}
		
		public function set y(value:Number):void {
			_y = value;
		}
		
		public function get x():Number {
			return _x;
		}
		
		public function set x(value:Number):void {
			_x = value;
		}
		
		public function get z():Number {
			return _z;
		}
		
		public function set z(value:Number):void {
			_z = value;
		}
		
		public function equals(point:PointGeometry):Boolean {
			var equals:Boolean = false;
			if (point != null) {
				equals = ((this._x == point.x && this._y == point.y && this._z == point.z) || (isNaN(this._x) && isNaN(this._y) && isNaN(point.x) && isNaN(point.y)));
			}
			return equals;
		}
		
		override public function getTolerancePoint(mousePoint:PointGeometry, distance:Number, snapPoint:PointGeometry):int {
			//            trace(mousePoint.x + ";" + mousePoint.y);
			//            trace("捕捉点距离:" + GMath.TwoPointDistance(this, mousePoint));
			//            trace("捕捉点容差:" + distance);
			if (GMath.TwoPointDistance(this, mousePoint) < distance) {
				snapPoint.x = this.x;
				snapPoint.y = this.y;
				return SnapTypeEnum.SNAP_OVERTEX;
			}
			else {
				return SnapTypeEnum.NO_SNAPS;
			}
		}
		
		public function toString():String {
			return "PointGeometry [x=" + x + ", y=" + y + ",z=" + z + "]";
		}
		
		public function clone():PointGeometry {
			var point:PointGeometry = new PointGeometry();
			point.x = this.x;
			point.y = this.y;
			point.z = this.z;
			return point;
		}
		
		override public function getLabelLocation():Location {
			return new Location(this.x, this.y);
		}
		
		override public function offset(location:Location):void {
			this.x = this.x + location.x;
			this.y = this.y + location.y;
		}
		
		/**
		 * 画锚点
		 */
		public function drawAnchorPoint(sprite:Sprite, map:Map):void {
			var i:int = 0;
			var k:int = 0;
			var point:Pixel = null;
			var anchor:AnchorPoint;
			var bfind:Boolean = false;
			
			point = map.getLayerPxFromLocation(new Location(this.x, this.y));
			var anchorLayer:GraphicLayer = map.getLayerById(LayerIdConstants.ANCHORLAYER_LAYERID) as GraphicLayer;
			if (null == anchorLayer) {
				Alert.show("---error ,anchorLayer is null ,where draw pointgeometry", "临时为了测试bug");
				//                trace("---error ,anchorLayer is null ,where draw pointgeometry");
			}
			var numLayers:int = map.layers.length;
			if (map.getLayerIndex(anchorLayer) != numLayers - 1) {
				map.changeLayerIndex(anchorLayer, 0);
			}
			//trace("画锚点------------------------:" + point.x + "  " + point.y);
			bfind = false;
			var childnum:Number = anchorLayer.numChildren;
			for (k = 0; k < childnum; k++) {
				if (anchorLayer.getChildAt(k) is AnchorPoint) {
					if ((anchorLayer.getChildAt(k) as AnchorPoint).geoPoint == this) {
						//锚点已经存在
						anchor = anchorLayer.getChildAt(k) as AnchorPoint;
						bfind = true;
					}
				}
			}
			if (!bfind) {
				anchor = new AnchorPoint();
				anchorLayer.addChild(anchor);
				anchor.pointIndex = 0;
				anchor.parentFeature = sprite as Feature;
				anchor.geoPoint = this;
			}
			anchor.x = point.x;
			anchor.y = point.y;
			
		}
		
		override public function isValid():Boolean {
			return true;
		}
		
		override public function hasPoint(point:PointGeometry):Boolean {
			if (this.x == point.x && this.y == point.y && this.z == point.z) {
				return true;
			}
			return false;
		}
		override public function getCenterPoint():PointGeometry{
			return new PointGeometry(this.x,this.y,this.z);
		}
		
	}
}